package com.sky.orangehireserver.modules.enterprise.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sky.orangehireserver.common.domain.Organization;
import com.sky.orangehireserver.common.domain.Users;
import com.sky.orangehireserver.common.service.OrganizationService;
import com.sky.orangehireserver.common.service.UsersService;
import com.sky.orangehireserver.enums.ResponseCodeEnum;
import com.sky.orangehireserver.enums.UserRoleEnum;
import com.sky.orangehireserver.exception.BizException;
import com.sky.orangehireserver.modules.enterprise.dto.EnterpriseEmployeeCreateDTO;
import com.sky.orangehireserver.modules.enterprise.dto.EnterpriseEmployeePasswordResetDTO;
import com.sky.orangehireserver.modules.enterprise.dto.EnterpriseEmployeeQueryDTO;
import com.sky.orangehireserver.modules.enterprise.dto.EnterpriseEmployeeUpdateDTO;
import com.sky.orangehireserver.modules.enterprise.service.EnterpriseAccountService;
import com.sky.orangehireserver.modules.enterprise.vo.EnterpriseEmployeeVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 企业账户管理服务实现类
 * 
 * @author sky
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EnterpriseAccountServiceImpl implements EnterpriseAccountService {

    private final UsersService usersService;
    private final OrganizationService organizationService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public EnterpriseEmployeeVO createEmployee(Long orgId, String currentUserRole, EnterpriseEmployeeCreateDTO createDTO) {
        log.info("开始创建企业员工，企业ID：{}，当前用户角色：{}，员工邮箱：{}", orgId, currentUserRole, createDTO.getEmail());
        
        // 检查企业是否存在且状态正常
        Organization organization = validateOrganization(orgId);
        
        // 检查权限：验证当前用户是否有权限创建指定角色的员工
        validateCreatePermission(currentUserRole, createDTO.getRole());
        
        // 检查邮箱是否已存在
        LambdaQueryWrapper<Users> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Users::getEmail, createDTO.getEmail());
        if (usersService.count(queryWrapper) > 0) {
            throw new BizException("EMAIL_EXISTS", "邮箱已存在");
        }
        
        // 加密密码
        String hashedPassword = BCrypt.hashpw(createDTO.getPassword());
        
        // 创建用户实体
        Users user = Users.builder()
                .orgId(orgId)
                .name(createDTO.getName())
                .email(createDTO.getEmail())
                .passwordHash(hashedPassword)
                .role(createDTO.getRole())
                .status("active") // 新创建的用户默认为激活状态
                .avatar(createDTO.getAvatar())
                .createdAt(LocalDateTime.now())
                .updatedAt(LocalDateTime.now())
                .build();
        
        // 保存用户
        boolean saved = usersService.save(user);
        if (!saved) {
            throw new BizException(ResponseCodeEnum.SYSTEM_ERROR.getErrorCode(), "创建企业员工失败");
        }
        
        log.info("企业员工创建成功，用户ID：{}", user.getId());
        return convertToVO(user, organization);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public EnterpriseEmployeeVO updateEmployee(Long orgId, String currentUserRole, EnterpriseEmployeeUpdateDTO updateDTO) {
        log.info("开始更新企业员工信息，企业ID：{}，当前用户角色：{}，员工ID：{}", orgId, currentUserRole, updateDTO.getId());
        
        // 检查企业是否存在且状态正常
        Organization organization = validateOrganization(orgId);
        
        // 检查员工是否存在且属于当前企业
        Users existingUser = validateEmployee(updateDTO.getId(), orgId);
        
        // 检查权限：验证当前用户是否有权限管理该员工
        validateManagePermission(currentUserRole, existingUser.getRole());
        
        // 如果更新邮箱，检查新邮箱是否已被其他用户使用
        if (StrUtil.isNotBlank(updateDTO.getEmail()) && !updateDTO.getEmail().equals(existingUser.getEmail())) {
            LambdaQueryWrapper<Users> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Users::getEmail, updateDTO.getEmail())
                    .ne(Users::getId, updateDTO.getId());
            if (usersService.count(queryWrapper) > 0) {
                throw new BizException("EMAIL_EXISTS", "邮箱已存在");
            }
        }
        
        // 如果更新角色，验证权限
        if (StrUtil.isNotBlank(updateDTO.getRole()) && !updateDTO.getRole().equals(existingUser.getRole())) {
            validateCreatePermission(currentUserRole, updateDTO.getRole());
        }
        
        // 更新用户信息（只更新非空字段）
        Users updateUser = new Users();
        updateUser.setId(updateDTO.getId());
        updateUser.setUpdatedAt(LocalDateTime.now());
        
        if (StrUtil.isNotBlank(updateDTO.getName())) {
            updateUser.setName(updateDTO.getName());
        }
        if (StrUtil.isNotBlank(updateDTO.getEmail())) {
            updateUser.setEmail(updateDTO.getEmail());
        }
        if (StrUtil.isNotBlank(updateDTO.getRole())) {
            updateUser.setRole(updateDTO.getRole());
        }
        if (StrUtil.isNotBlank(updateDTO.getStatus())) {
            updateUser.setStatus(updateDTO.getStatus());
        }
        if (StrUtil.isNotBlank(updateDTO.getAvatar())) {
            updateUser.setAvatar(updateDTO.getAvatar());
        }
        
        // 执行更新
        boolean updated = usersService.updateById(updateUser);
        if (!updated) {
            throw new BizException(ResponseCodeEnum.SYSTEM_ERROR.getErrorCode(), "更新企业员工信息失败");
        }
        
        // 返回更新后的用户信息
        Users updatedUser = usersService.getById(updateDTO.getId());
        log.info("企业员工信息更新成功，员工ID：{}", updateDTO.getId());
        return convertToVO(updatedUser, organization);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteEmployee(Long orgId, String currentUserRole, Long employeeId) {
        log.info("开始删除企业员工，企业ID：{}，当前用户角色：{}，员工ID：{}", orgId, currentUserRole, employeeId);
        
        // 检查企业是否存在且状态正常
        validateOrganization(orgId);
        
        // 检查员工是否存在且属于当前企业
        Users employee = validateEmployee(employeeId, orgId);
        
        // 检查权限：验证当前用户是否有权限删除该员工
        validateManagePermission(currentUserRole, employee.getRole());
        
        // TODO: 检查员工是否还有相关的业务数据，如果有则不允许删除
        // 这里可以根据业务需求添加相关检查逻辑
        
        // 执行删除
        boolean deleted = usersService.removeById(employeeId);
        if (!deleted) {
            throw new BizException(ResponseCodeEnum.SYSTEM_ERROR.getErrorCode(), "删除企业员工失败");
        }
        
        log.info("企业员工删除成功，员工ID：{}", employeeId);
    }

    @Override
    public EnterpriseEmployeeVO getEmployeeById(Long orgId, Long employeeId) {
        log.info("查询企业员工详情，企业ID：{}，员工ID：{}", orgId, employeeId);
        
        // 检查企业是否存在
        Organization organization = organizationService.getById(orgId);
        if (organization == null) {
            throw new BizException("ORGANIZATION_NOT_FOUND", "企业不存在");
        }
        
        // 检查员工是否存在且属于当前企业
        Users employee = validateEmployee(employeeId, orgId);
        
        return convertToVO(employee, organization);
    }

    @Override
    public IPage<EnterpriseEmployeeVO> getEmployeePage(Long orgId, String currentUserRole, EnterpriseEmployeeQueryDTO queryDTO) {
        log.info("分页查询企业员工列表，企业ID：{}，当前用户角色：{}，查询条件：{}", orgId, currentUserRole, queryDTO);
        
        // 检查企业是否存在
        Organization organization = organizationService.getById(orgId);
        if (organization == null) {
            throw new BizException("ORGANIZATION_NOT_FOUND", "企业不存在");
        }
        
        // 获取当前用户可管理的角色列表
        List<String> manageableRoles = getManageableRoles(currentUserRole);
        
        // 构建查询条件
        LambdaQueryWrapper<Users> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Users::getOrgId, orgId)
                .in(!manageableRoles.isEmpty(), Users::getRole, manageableRoles)
                .like(StrUtil.isNotBlank(queryDTO.getName()), Users::getName, queryDTO.getName())
                .like(StrUtil.isNotBlank(queryDTO.getEmail()), Users::getEmail, queryDTO.getEmail())
                .eq(StrUtil.isNotBlank(queryDTO.getRole()), Users::getRole, queryDTO.getRole())
                .eq(StrUtil.isNotBlank(queryDTO.getStatus()), Users::getStatus, queryDTO.getStatus())
                .orderByDesc(Users::getCreatedAt);
        
        // 分页查询
        Page<Users> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        IPage<Users> userPage = usersService.page(page, queryWrapper);
        
        // 转换为VO
        IPage<EnterpriseEmployeeVO> voPage = new Page<>(userPage.getCurrent(), userPage.getSize(), userPage.getTotal());
        List<EnterpriseEmployeeVO> voList = userPage.getRecords().stream()
                .map(user -> convertToVO(user, organization))
                .collect(Collectors.toList());
        voPage.setRecords(voList);
        
        return voPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void enableEmployee(Long orgId, String currentUserRole, Long employeeId) {
        log.info("启用企业员工，企业ID：{}，当前用户角色：{}，员工ID：{}", orgId, currentUserRole, employeeId);
        updateEmployeeStatus(orgId, currentUserRole, employeeId, "active");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disableEmployee(Long orgId, String currentUserRole, Long employeeId) {
        log.info("禁用企业员工，企业ID：{}，当前用户角色：{}，员工ID：{}", orgId, currentUserRole, employeeId);
        updateEmployeeStatus(orgId, currentUserRole, employeeId, "inactive");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetEmployeePassword(Long orgId, String currentUserRole, EnterpriseEmployeePasswordResetDTO resetDTO) {
        log.info("重置企业员工密码，企业ID：{}，当前用户角色：{}，员工ID：{}", orgId, currentUserRole, resetDTO.getId());
        
        // 检查企业是否存在且状态正常
        validateOrganization(orgId);
        
        // 检查员工是否存在且属于当前企业
        Users employee = validateEmployee(resetDTO.getId(), orgId);
        
        // 检查权限：验证当前用户是否有权限重置该员工密码
        validateManagePermission(currentUserRole, employee.getRole());
        
        // 加密新密码
        String hashedPassword = BCrypt.hashpw(resetDTO.getNewPassword());
        
        // 更新密码
        Users updateUser = new Users();
        updateUser.setId(resetDTO.getId());
        updateUser.setPasswordHash(hashedPassword);
        updateUser.setUpdatedAt(LocalDateTime.now());
        
        boolean updated = usersService.updateById(updateUser);
        if (!updated) {
            throw new BizException(ResponseCodeEnum.SYSTEM_ERROR.getErrorCode(), "重置密码失败");
        }
        
        log.info("企业员工密码重置成功，员工ID：{}", resetDTO.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteEmployees(Long orgId, String currentUserRole, List<Long> employeeIds) {
        log.info("批量删除企业员工，企业ID：{}，当前用户角色：{}，员工ID列表：{}", orgId, currentUserRole, employeeIds);
        
        if (employeeIds == null || employeeIds.isEmpty()) {
            throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode(), "员工ID列表不能为空");
        }
        
        // 检查企业是否存在且状态正常
        validateOrganization(orgId);
        
        // 检查所有员工是否都属于当前企业，并验证权限
        List<Users> employees = usersService.listByIds(employeeIds);
        for (Users employee : employees) {
            if (!orgId.equals(employee.getOrgId())) {
                throw new BizException("EMPLOYEE_NOT_BELONG_TO_ORG", "员工不属于当前企业");
            }
            validateManagePermission(currentUserRole, employee.getRole());
        }
        
        // TODO: 检查员工是否还有相关的业务数据，如果有则不允许删除
        // 这里可以根据业务需求添加相关检查逻辑
        
        // 执行批量删除
        boolean deleted = usersService.removeByIds(employeeIds);
        if (!deleted) {
            throw new BizException(ResponseCodeEnum.SYSTEM_ERROR.getErrorCode(), "批量删除企业员工失败");
        }
        
        log.info("批量删除企业员工成功，删除数量：{}", employeeIds.size());
    }

    @Override
    public List<String> getManageableRoles(String currentUserRole) {
        if (UserRoleEnum.isAdmin(currentUserRole)) {
            // 企业管理员可以管理HR
            return Arrays.asList(UserRoleEnum.RECRUITER.getCode());
        } else if (UserRoleEnum.isRecruiter(currentUserRole)) {
            // 企业HR可以管理面试官、助理、普通员工
            return Arrays.asList(
                UserRoleEnum.INTERVIEWER.getCode(),
                UserRoleEnum.ASSISTANT.getCode(),
                UserRoleEnum.ORDINARY_EMPLOYEES.getCode()
            );
        }
        return Collections.emptyList();
    }

    /**
     * 验证企业是否存在且状态正常
     * 
     * @param orgId 企业ID
     * @return 企业实体
     */
    private Organization validateOrganization(Long orgId) {
        Organization organization = organizationService.getById(orgId);
        if (organization == null) {
            throw new BizException("ORGANIZATION_NOT_FOUND", "企业不存在");
        }
        if (!"active".equals(organization.getStatus())) {
            throw new BizException("ORGANIZATION_INACTIVE", "企业未激活");
        }
        return organization;
    }

    /**
     * 验证员工是否存在且属于指定企业
     * 
     * @param employeeId 员工ID
     * @param orgId 企业ID
     * @return 员工实体
     */
    private Users validateEmployee(Long employeeId, Long orgId) {
        Users employee = usersService.getById(employeeId);
        if (employee == null) {
            throw new BizException("EMPLOYEE_NOT_FOUND", "员工不存在");
        }
        if (!orgId.equals(employee.getOrgId())) {
            throw new BizException("EMPLOYEE_NOT_BELONG_TO_ORG", "员工不属于当前企业");
        }
        return employee;
    }

    /**
     * 验证创建权限
     * 
     * @param currentUserRole 当前用户角色
     * @param targetRole 目标角色
     */
    private void validateCreatePermission(String currentUserRole, String targetRole) {
        List<String> manageableRoles = getManageableRoles(currentUserRole);
        if (!manageableRoles.contains(targetRole)) {
            throw new BizException("PERMISSION_DENIED", "没有权限创建该角色的用户");
        }
    }

    /**
     * 验证管理权限
     * 
     * @param currentUserRole 当前用户角色
     * @param targetRole 目标角色
     */
    private void validateManagePermission(String currentUserRole, String targetRole) {
        List<String> manageableRoles = getManageableRoles(currentUserRole);
        if (!manageableRoles.contains(targetRole)) {
            throw new BizException("PERMISSION_DENIED", "没有权限管理该角色的用户");
        }
    }

    /**
     * 更新员工状态
     * 
     * @param orgId 企业ID
     * @param currentUserRole 当前用户角色
     * @param employeeId 员工ID
     * @param status 状态
     */
    private void updateEmployeeStatus(Long orgId, String currentUserRole, Long employeeId, String status) {
        // 检查企业是否存在且状态正常
        validateOrganization(orgId);
        
        // 检查员工是否存在且属于当前企业
        Users employee = validateEmployee(employeeId, orgId);
        
        // 检查权限：验证当前用户是否有权限管理该员工
        validateManagePermission(currentUserRole, employee.getRole());
        
        // 更新状态
        Users updateUser = new Users();
        updateUser.setId(employeeId);
        updateUser.setStatus(status);
        updateUser.setUpdatedAt(LocalDateTime.now());
        
        boolean updated = usersService.updateById(updateUser);
        if (!updated) {
            throw new BizException(ResponseCodeEnum.SYSTEM_ERROR.getErrorCode(), "更新员工状态失败");
        }
    }

    /**
     * 将Users实体转换为EnterpriseEmployeeVO
     * 
     * @param user 用户实体
     * @param organization 企业实体
     * @return 企业员工VO
     */
    private EnterpriseEmployeeVO convertToVO(Users user, Organization organization) {
        EnterpriseEmployeeVO vo = BeanUtil.copyProperties(user, EnterpriseEmployeeVO.class);
        
        // 设置企业信息
        if (organization != null) {
            vo.setOrgName(organization.getName());
        }
        
        // 设置角色名称
        UserRoleEnum roleEnum = UserRoleEnum.getByCode(user.getRole());
        if (roleEnum != null) {
            vo.setRoleName(roleEnum.getName());
        }
        
        return vo;
    }
}